#ifndef SINGLECONFIG_H
#define SINGLECONFIG_H

#include <memory>
#include <string>
/*
 * pur @ configure的单态访问模式
 *      1、程序开始时调用SetConfigPath设置相关配置文件存放路径
 *      2、程序结束时调用Release释放相关资源
 *      3、程序中调用GetValue获取相关的key - value值
 *		4、只能读取.conf结尾的配置文件
 *		5、通过AddAutoReloadFile加载需要自动更新的配置文件
 *		6、通过StartAutoReload启动自动更新线程，并设置更新周期
 *		7、通过SetDefaultValue设置配置文件中key的默认参数
 * author @ haibin.wang
 * data @ 2013.10.11
 *
 * use example
 *      std::string errInfo;
 *      SingleConfig::SetConfigPath(filePath,errInfo);
 *      SingleConfig::SetDefaultValue(modulename, key, value);//设置key的默认值为value
 *      SingleConfig::SetDefaultValue(modulename, key, (long
 *long)value);//设置key的默认值为long long 型的value
 *      SingleConfig::AddAutoReloadFile(filePath); //设置自动监测变化配置文件
 *      SingleConfig::StartAutoReload(30); //设置30秒监测一次配置文件是否有变化
 *
 *      SingleConfig::GetStrValue(modulename, key);//获取字符数据
 *      SingleConfig::GetIntValue(modulename, key);//获取整型数据
 *      SingleConfig::GetDoubleValue(modulename, key);//获取double型数据
 *      SingleConfig::GetLongValue(modulename, )key);//获取long或long long型数据
 *      SingleConfig::GetBoolValue(modulename, key);//获取bool型数据
 *
 *      SingleConfig::Release(); //程序退出时必须调用release函数释放内存
 * */

class ConfigureInfo;
class SingleConfig {
    public:
    /*
     * pur @ 设置读取的文件路径，并初始化相关资源
     * para @ dir 要读取的配置文件目录
     * para @ bChild 是否循环读取子目录
     * para @ err 错误信息
     * return @ true 无错误，false 有错误，查看err信息
     */
    static bool SetConfigPath(const char *dir, bool bChild, std::string &err);

    /* pur @ 设置读取单个配置文件，并初始化相关资源
     * para @ configFile 要读取的配置文件的全路径
     * para @ err 错误信息
     * return @  true 无错误，false 有错误，查看err信息
    */
    static bool SetConfigPath(const char *configFile, std::string &err);

    /* pur @ 设置默认配置参数
     * para @ filename 配置文件名,不能为NULL
     * para @ key 配置项的key, 不能为NULL
     * para @ defValue 默认的value值
     * return @ true设置成功，false 设置失败，filename或key为NULL
     */
    static bool SetDefaultValue(const char *filename, const char *key, const char *defValue);
    static bool SetDefaultValue(const char *filename, const char *key, const int &defValue);
    static bool SetDefaultValue(const char *filename, const char *key, const long long &defValue);
    static bool SetDefaultValue(const char *filename, const char *key, const double &defValue);

    /*
     * pur @ 释放申请的资源，在程序退出时调用
     */
    static void Release();

    /*
     * pur @ 根据模块名和key获取value
     * para @ modulename 配置文件名带后缀名
     * para @ key 要读取的key值
     * return @ 返回读取的字符串value值，空说明没有相关配置项
     */
    static std::string GetStrValue(const char *modulename, const char *key);

    /*
     * pur @ 根据模块名和key获取value
     * para @ modulename 配置文件名带后缀名
     * para @ key 要读取的key值
     * return @ 返回读取的数字value值，-65536说明没读取到
     */
    static int GetIntValue(const char *modulename, const char *key);

    /* --- 暂未实现
     * pur @ 根据模块名和key获取value
     * para @ modulename 配置文件名带后缀名
     * para @ key 要读取的key值
     * return @ 返回读取的数字value值，-65536说明没读取到
     */
    static double GetDoubleValue(const char *modulename, const char *key);

    /* --- 暂未实现
     * pur @ 根据模块名和key获取value
     * para @ modulename 配置文件名带后缀名
     * para @ key 要读取的key值
     * return @ 返回读取的数字value值，-65536说明没读取到
     */
    static long long GetLongValue(const char *modulename, const char *key);
    /*
     * pur @ 根据模块名和key获取value
     * para @ modulename 配置文件名带后缀名
     * para @ key 要读取的key值
     * return @ 返回读取的bool型的value值，读取到1返回true，其他值为false;
     */
    static bool GetBoolValue(const char *modulename, const char *key);

    /*
     * pur @ 重新加载模块配置文件
     * para @ modulename 配置文件全路径带后缀名 eg:/home/test/a.conf
     * return @
     * 返回true说明加载成功，false说明失败，需要检查文件modulename是否存在及是否有读权限
     */
    static bool ReloadModule(const char *modulename);

    /* pur @ 添加自动定时重新加载的配置文件
     * para @ filepath 配置文件全路径包含文件名
     * return @
    */
    static void AddAutoReloadFile(const char *filepath);

    /* pur @ 启动自动定时重新加载配置文件
     * para @ checkInter 自动检测配置文件变化的时间间隔,
     *          单位：秒，必须大于等于1，否则不会启动自动更新配置文件功能
    */
    static void StartAutoReload(const int &checkInter);

    public: //以下为一些辅助函数
    /* pur @ 根据给定的路径名获取文件的名字，不判定文件是否存在
     * para @ filePath 文件全路径或文件名
     * return @  返回符合要求的文件名，如果没有截取到文件名会返回空，
     * example
     *          filePath = /home/test/1.log 返回1.log
     *          filePath = 2.log            返回2.log
    */
    static std::string GetFileName(const char *filePath);

    protected:
    explicit SingleConfig(){};
    virtual ~SingleConfig();

    private:
    /*
     * pur @ 初始化相关资源
     */
    static SingleConfig *Instance();

    static SingleConfig *m_instance;
    static ConfigureInfo *m_conf;
};
#endif
